package hammersmith.local.management;

import hammersmith.local.exceptions.ArticleNotFoundException;
import hammersmith.local.exceptions.EmptyCartException;
import hammersmith.local.exceptions.StockTooLowException;
import hammersmith.local.exceptions.WrongInputException;
import hammersmith.local.exceptions.WrongMinCountException;
import hammersmith.local.persistence.DBHandler;
import hammersmith.local.valueobjects.Article;
import hammersmith.local.valueobjects.Customer;
import hammersmith.local.valueobjects.Employee;
import hammersmith.local.valueobjects.Invoice;
import hammersmith.local.valueobjects.Log;
import hammersmith.local.valueobjects.Person;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Hashtable;

/**
 * 
 * ShopManagement-Klasse
 * 
 * @author hammersmith
 * 
 */
public class ShopManagement implements Serializable {
	private static final long serialVersionUID = -2851671480837736438L;
	private String name;
	private String adress;

	private LogManagement logger;

	private DBHandler handler;
	private ArticleManagement articleManagement;
	private CustomerManagement customerManagement;
	private EmployeeManagement employeeManagement;
	private ShopServices service;

	// Leerer Konstruktor
	public ShopManagement() {
	}

	// Konstruktor
	public ShopManagement(String name, String adress) {
		this.name = name;
		this.adress = adress;
		this.articleManagement = new ArticleManagement();
		this.customerManagement = new CustomerManagement();
		this.employeeManagement = new EmployeeManagement();
		this.service = new ShopServices();
		this.logger = new LogManagement();
		this.handler = new DBHandler();
	}

	
	// Getter und Setter
	public String getAdress() {
		return adress;
	}

	public ArticleManagement getArticleManagement() {
		return articleManagement;
	}

	public CustomerManagement getCustomerManagement() {
		return customerManagement;
	}

	public EmployeeManagement getEmployeeManagement() {
		return employeeManagement;
	}

	public DBHandler getHandler() {
		return handler;
	}

	public LogManagement getLogger() {
		return logger;
	}

	public String getName() {
		return name;
	}

	public ShopServices getService() {
		if (this.service == null) {
			this.service = new ShopServices();
			return this.service;
		} else {
			return service;
		}
	}

	public void setAdress(String adress) {
		this.adress = adress;
	}

	public void setArticleManagement(ArticleManagement articleManagement) {
		this.articleManagement = articleManagement;
	}

	public void setCustomerManagement(CustomerManagement customerManagement) {
		this.customerManagement = customerManagement;
	}

	public void setEmployeeManagement(EmployeeManagement employeeManagement) {
		this.employeeManagement = employeeManagement;
	}

	public void setHandler(DBHandler handler) {
		this.handler = handler;
	}

	public void setLogger(LogManagement logger) {
		this.logger = logger;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setService(ShopServices service) {
		this.service = service;
	}

	/*
	 * ARTIKELMETHODEN!
	 */
	public Article addNewArticle(Employee e, String name, String description,
			int stock, String size, float price, String color, String type,
			int minCount) throws WrongInputException, WrongMinCountException {

		Article newArticle = this.articleManagement.addNewArticle(e, name,
				description, stock, size, price, color, type, minCount);

		this.logger.addLog(e, newArticle, stock, "hinzugefuegt");

		saveDB();
		return newArticle;
	}
	
	public Article editArticles(Employee e, Article article, String type, String name, String size, String color, String stock, String price, String minCount, String description) {		
		Article a = articleManagement.editArticles(article, type, name, size, color, stock, price, minCount, description);
		
		this.logger.addLog(e, a, a.getStock(), "veraendert");

		saveDB();
		
		return article;
	}

	public void deleteArticle(Employee e, Article a) {
		int stock = this.articleManagement.deleteArticle(e, a);
		log(e, a, stock, "gelöscht");
		saveDB();
	}

	/*
	 * KUNDENMETHODEN!
	 */
	public int addNewCustomer(String name, String firstname, String street,
			String zip, String city, String mail, String pw) {

		int id = this.customerManagement.addNewCustomer(name, firstname, street, zip,
				city, mail, pw);
		saveDB();
		return id;
	}

	public Customer loginCustomer(String user, String pw) {
		Customer c = this.customerManagement.loginAsCustomer(user, pw);
		return c;
	}

	public void editCartStock(Customer c, long id, int count)
			throws WrongMinCountException, ArticleNotFoundException, StockTooLowException {
		Article a = articleManagement.getArticleById(id);
		c.getCart().editStock(a, count);
		log(c, a, count, "verändert");
		
		saveDB();
	}

	public Invoice buy(Customer c) throws EmptyCartException {
		Object [] objList = this.service.buy(c,
				this.customerManagement.getCustomerList(), logger);

		ArrayList<Log> logList = (ArrayList<Log>) objList[0];
		
		for (Log log : logList) {
			logger.addLog(log.getActor(), log.getArticle(), log.getCount(),
					log.getWhat());
		}

		saveDB();
		
		return (Invoice) objList[1];
	}
	
	/*
	 * MITARBEITERMETHODEN
	 */

	public Employee loginEmployee(String user, String pw) {
		Employee e = this.employeeManagement.loginAsEmployee(user, pw);
		return e;
	}

	/*
	 * WARENKORB METHODEN
	 */
	public void addToCart(Customer c, Article a, int count)
			throws StockTooLowException, WrongMinCountException {
		this.service = new ShopServices();
		this.service.addToCart(c, a, count);
		
		saveDB();
	}

	public void removeArticleFromCart(Customer c, long id)
			throws EmptyCartException, ArticleNotFoundException {
		Article a = articleManagement.getArticleById(id);
		c.getCart().removeArticleFromCart(a);
		saveDB();
	}
	
	public Article getArticleByName(String name){
		
		ArrayList<Article> articleList = articleManagement.getArticleList();
		
		for (Article a : articleList) {
			if(a.getName().equals(name)){
				return a;
			}
		}
		return null;
	}
	
	public Article getArticleBySizeColorAndName(String name, String size, String color){
		
		ArrayList<Article> list = articleManagement.getArticleList();
		for (Article article : list) {
			if(article.getName().equals(name) && article.getSize().equals(size) && article.getColor().equals(color)){
				return article;
			}
		}
		
		return null;
	}

	/*
	 * UTIL
	 */

	public void log(Person p, Article article, int newVal, String kind) {
		logger.addLog(p, article, newVal, kind);
	}

	public boolean checkNumeric(String in) {
		boolean ok = this.articleManagement.isNumeric(in, "i");
		return ok;
	}

	public void saveDB() {
		handler.saveShop(this);
	}

	public ShopManagement loadDB() {
		ShopManagement shop = handler.loadShop();
		return shop;
	}
	
	public Hashtable<String, ArrayList<String>> getAllArticlesByType(String type){
		this.service = new ShopServices();
		Hashtable<String, ArrayList<String>> all = this.service.getAllArticlesByType(articleManagement.getArticleList(),type);
		
		return all;
	}
	
	public ArrayList<String> getAllColorsBySizeAndName(String size, String name){
		this.service = new ShopServices();
		ArrayList<String> allColors = this.service.getAllColorsBySizeAndName(articleManagement.getArticleList(), size, name);
		
		return allColors;
	}
	
	public String createNews(String txt) {
		this.service = new ShopServices();
		return this.service.createNews(txt);
	}
	
	public Integer getRefreshedCartCount(Customer customer){
		int count = customer.getCart().getList().size();
		return count;
	}

}